package com.vhall.component.service.goods.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vhall.component.dao.goods.LiveGoodsStatsDetailMapper;
import com.vhall.component.dao.goods.LiveGoodsStatsMapper;
import com.vhall.component.dao.room.RoomGoodsMapper;
import com.vhall.component.dao.room.RoomMapper;
import com.vhall.component.entity.goods.LiveGoodsStatsDetailEntity;
import com.vhall.component.entity.goods.LiveGoodsStatsEntity;
import com.vhall.component.entity.goods.dto.GuoPrdInfoDTO;
import com.vhall.component.entity.goods.dto.GuoXinPrdInfoDTO;
import com.vhall.component.entity.goods.dto.ProdInfoGuoXinDTO;
import com.vhall.component.entity.goods.dto.SearchProdGuoXinDTO;
import com.vhall.component.entity.goods.enums.GuoXinOftypeEnum;
import com.vhall.component.entity.goods.enums.GuoxinPrdTypeEnum;
import com.vhall.component.entity.goods.goods.GoodsStatisVO;
import com.vhall.component.entity.goods.vo.GetGoodsInfoRequestVO;
import com.vhall.component.entity.goods.vo.GetGoodsInfoResponseVO;
import com.vhall.component.entity.goods.vo.SearchGoodsPageRequestVO;
import com.vhall.component.entity.goods.vo.SearchGoodsResponseVO;
import com.vhall.component.entity.page.vo.PageVO;
import com.vhall.component.entity.room.entity.RoomGoodsEntity;
import com.vhall.component.entity.room.entity.RoomsEntity;
import com.vhall.component.entity.room.enums.BusinessAuthEnum;
import com.vhall.component.entity.room.enums.InvestPeriodEnum;
import com.vhall.component.entity.room.enums.InvestVarietyEnum;
import com.vhall.component.entity.room.enums.RoomAuditStatusEnum;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.plugin.common.constant.RedisKey;
import com.vhall.component.plugin.common.enums.GoodsPrdTypeEnum;
import com.vhall.component.plugin.common.enums.GoodsRiskLevelEnum;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.support.Token;
import com.vhall.component.plugin.common.support.TokenThreadLocal;
import com.vhall.component.plugin.core.service.GuoXinService;
import com.vhall.component.service.goods.GuoxinPrdService;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * GuoxinPrdServiceImpl-
 *
 * @author xing.wang
 * @date 2023/8/24
 */
@Service
@Slf4j
public class GuoxinPrdServiceImpl implements GuoxinPrdService {
    @Resource
    private GuoXinService guoXinService;
    @Resource
    private RoomGoodsMapper roomGoodsMapper;
    @Resource
    private RoomMapper roomMapper;
    @Resource
    private LiveGoodsStatsMapper liveGoodsStatsMapper;
    @Resource
    private LiveGoodsStatsDetailMapper liveGoodsStatsDetailMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public PageVO<SearchGoodsResponseVO> searchGoodsPage(SearchGoodsPageRequestVO vo) {
        Token token = TokenThreadLocal.getToken();
        SearchProdGuoXinDTO dto = new SearchProdGuoXinDTO();
        Integer page = vo.getPage();
        dto.setPageNo(page);
        Integer pageSize = vo.getPageSize();
        dto.setPageSize(pageSize);
        dto.setNotesid(token.getThirdPartyUserId());
        dto.setPrdQuery(vo.getKeyword());
        dto.setPrdType(vo.getPrdType());
        JSONObject searchProd = guoXinService.searchProd(dto);
        if (Objects.isNull(searchProd)) {
            return new PageVO(page, pageSize, 0, new ArrayList());
        }
        JSONObject pageInfo = searchProd.getJSONObject("pageInfo");
        Integer total = pageInfo.getInteger("total");
        JSONArray list = searchProd.getJSONArray("list");
        List<SearchGoodsResponseVO> result = new ArrayList<>();
        int size = list.size();
        SearchGoodsResponseVO temp;
        for (int i = 0; i < size; i++) {
            temp = new SearchGoodsResponseVO();
            JSONObject jsonObject = list.getJSONObject(i);
            String prdCode = jsonObject.getString("prdCode");
            String prdName = jsonObject.getString("prdName");
            String prdUseCaseStr = jsonObject.getString("prdUseCase");
            Integer prdTypeInt = getJsonAttributeInteger(jsonObject, "prdType");
            Integer prdRiskLevelInt = getJsonAttributeInteger(jsonObject, "prdRiskLevel");
            Integer prdInvestTypeInt = getJsonAttributeInteger(jsonObject, "prdInvestType");
            Integer prdInvestPeriodInt = getJsonAttributeInteger(jsonObject, "prdInvestPeriod");
            temp.setPrdCode(prdCode);
            temp.setPrdName(prdName);
            temp.setPrdType(prdTypeInt);
            temp.setPrdTypeName(GuoxinPrdTypeEnum.getNameByValue(prdTypeInt));
            temp.setPrdRiskLevel(prdRiskLevelInt);
            temp.setPrdRiskLevelName(GoodsRiskLevelEnum.getNameByValue(String.valueOf(prdRiskLevelInt)));
            temp.setPrdUseCase(prdUseCaseStr);
            temp.setPrdUseCaseName(BusinessAuthEnum.getNameByValue(prdUseCaseStr));
            temp.setPrdInvestPeriod(prdInvestPeriodInt);
            temp.setPrdInvestPeriodName(InvestPeriodEnum.getNameByValue(String.valueOf(prdInvestPeriodInt)));
            temp.setPrdInvestType(prdInvestTypeInt);
            temp.setPrdInvestTypeName(InvestVarietyEnum.getNameByValue(String.valueOf(prdInvestTypeInt)));
            result.add(temp);
        }
        return new PageVO(page, pageSize, total, result);
    }

    @NotNull
    private Integer getJsonAttributeInteger(JSONObject jsonObject, String attributeName) {
        Object dataObj = jsonObject.get(attributeName);
        Integer dataInt = 0;
        if (Objects.nonNull(dataObj) && dataObj instanceof Integer) {
            dataInt = (Integer) dataObj;
        }
        return dataInt;
    }

    @Override
    public PageVO<SearchGoodsResponseVO> searchRoomGoods(Integer ilId, int pageNum, int pageSize) {
        PageVO<SearchGoodsResponseVO> pageVO = new PageVO<>();
        Page<RoomGoodsEntity> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<RoomGoodsEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(RoomGoodsEntity::getIlId, ilId);
        queryWrapper.eq(RoomGoodsEntity::getIsDeleted, 0);
        page = roomGoodsMapper.selectPage(page, queryWrapper);
        if (CollUtil.isNotEmpty(page.getRecords())) {
            pageVO.setCurrentPage(pageNum);
            pageVO.setTotal((int) page.getTotal());
            List<SearchGoodsResponseVO> list = new ArrayList<>();
            for (RoomGoodsEntity entity : page.getRecords()) {
                SearchGoodsResponseVO vo = new SearchGoodsResponseVO();
                vo.setId(entity.getId());
                vo.setPrdCode(entity.getPrdCode());
                vo.setPrdName(entity.getPrdName());
                vo.setPrdInvestType(entity.getPrdInvestType());
                vo.setPrdInvestTypeName(InvestVarietyEnum.getNameByValue(String.valueOf(entity.getPrdInvestType())));
                vo.setPrdType(entity.getPrdType());
                vo.setPrdTypeName(GuoxinPrdTypeEnum.getNameByValue(entity.getPrdType()));
                vo.setPrdRiskLevel(entity.getPrdRiskLevel());
                vo.setPrdRiskLevelName(GoodsRiskLevelEnum.getNameByValue(String.valueOf(entity.getPrdRiskLevel())));
                //无要求:0,1:融资融券,^:港股通,E:创业板,k:科创板,w:股票期权,x:北交所
                vo.setPrdUseCaseName(useCase(entity.getPrdUseCase()));
                vo.setPrdUseCase(entity.getPrdUseCase());
                vo.setPrdInvestPeriod(entity.getPrdInvestPeriod());
                vo.setPrdInvestPeriodName(InvestPeriodEnum.getNameByValue(String.valueOf(entity.getPrdInvestPeriod())));
                list.add(vo);
            }
            pageVO.setData(list);
        }
        return pageVO;
    }

    private String useCase(String code) {
        String name = "";
        if (StrUtil.isEmpty(code)) {
            return "";
        }
        try {
            switch (code) {
                case "0":
                    name = "无要求";
                    break;
                case "1":
                    name = "融资融券";
                    break;
                case "^":
                    name = "港股通";
                    break;
                case "E":
                    name = "创业板";
                    break;
                case "k":
                    name = "科创板";
                    break;
                case "w":
                    name = "股票期权";
                    break;
                case "x":
                    name = "北交所";
                    break;
            }
        } catch (Exception e) {
            log.error("业务权限转换异常:{}", e);
        }
        return name;
    }

    @Override
    public List<GetGoodsInfoResponseVO> getGoodsInfoList(GetGoodsInfoRequestVO vo) {
        List<GetGoodsInfoResponseVO> result = new ArrayList<>();
        String prdCodes = vo.getPrdCodes();

        ProdInfoGuoXinDTO dto = new ProdInfoGuoXinDTO();
        dto.setPrdCodes(prdCodes);
        dto.setRoomId(vo.getIlId());
        dto.setShareid(vo.getShareid());

        JSONArray jsonArray = guoXinService.prodInfo(dto);
        int size = jsonArray.size();
        for (int i = 0; i < size; i++) {
            GetGoodsInfoResponseVO temp = new GetGoodsInfoResponseVO();
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            Integer prdType = jsonObject.getInteger("prdType");
            String prdClass = jsonObject.getString("prdClass");
            String prdName = jsonObject.getString("prdName");
            String prdCode = jsonObject.getString("prdCode");
            String prdDesc = jsonObject.getString("prdDesc");


            Integer prdRiskLevel = jsonObject.getInteger("prdRiskLevel");
            Integer prdInvestType = jsonObject.getInteger("prdInvestType");
            Integer prdInvestPeriod = jsonObject.getInteger("prdInvestPeriod");
            String prdUseCase = jsonObject.getString("prdUseCase");


            String prdCreater = jsonObject.getString("prdCreater");
            String prdDept = jsonObject.getString("prdDept");
            String jtyUrl = jsonObject.getString("jtyUrl");
            String wxUrl = jsonObject.getString("wxUrl");


            Integer status = jsonObject.getInteger("status");

            String sincestart = jsonObject.getString("sincestart");
            String threeyear = jsonObject.getString("threeyear");
            String oneyear = jsonObject.getString("oneyear");
            String sixmonth = jsonObject.getString("sixmonth");
            String threemonth = jsonObject.getString("threemonth");
            String onemonth = jsonObject.getString("onemonth");
            String cjgm = jsonObject.getString("cjgm");
            String oftype = jsonObject.getString("oftype");

            String zlr = jsonObject.getString("zlr");
            String xhy = jsonObject.getString("xhy");
            String cover = jsonObject.getString("cover");
            temp.setSerialNumber(i + 1);

//            系统内商品 id
            LambdaQueryWrapper<RoomGoodsEntity> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(RoomGoodsEntity::getIlId, vo.getIlId());
            queryWrapper.eq(RoomGoodsEntity::getPrdCode, prdCode);
            queryWrapper.last(" limit 1");
            RoomGoodsEntity roomGoodsEntity = roomGoodsMapper.selectOne(queryWrapper);
            temp.setBcgId(roomGoodsEntity.getId());
            temp.setBgId(roomGoodsEntity.getId());
            temp.setCjgm(cjgm);
            temp.setOnemonth(income(onemonth));
            temp.setJtyUrl(jtyUrl);
            temp.setOneyear(income(oneyear));
            temp.setPrdClass(prdClass);
            temp.setPrdCreater(prdCreater);
            temp.setPrdDept(prdDept);
            temp.setPrdDesc(prdDesc);
            temp.setSincestart(income(sincestart));
            temp.setSixmonth(income(sixmonth));
            temp.setStatus(status);
            temp.setThreeyear(income(threeyear));
            temp.setWxUrl(wxUrl);
            temp.setPrdRiskLevel(prdRiskLevel);
            temp.setPrdRiskLevelName(GoodsRiskLevelEnum.getNameByValue(String.valueOf(prdRiskLevel)));
            temp.setPrdInvestType(prdInvestType);
            temp.setPrdInvestTypeName(InvestVarietyEnum.getNameByValue(String.valueOf(prdInvestType)));
            temp.setPrdInvestPeriod(prdInvestPeriod);
            temp.setPrdCode(prdCode);
            temp.setPrdUseCase(BusinessAuthEnum.getCodeByValue(prdUseCase));
            temp.setThreemonth(income(threemonth));
            temp.setPrdType(prdType);
            temp.setPrdTypeName(GuoxinPrdTypeEnum.getNameByValue(prdType));
            temp.setPrdName(prdName);
            temp.setOftype(oftype);
            temp.setOftypeName(GuoXinOftypeEnum.getNameByValue(oftype));
            temp.setZlr(zlr);
            temp.setXhy(income(xhy));
            if (StrUtil.isNotEmpty(cover)){
                temp.setPrdImage(cover);
            }else {
                if (temp.getPrdType() == 3) {
                    // 模版B
                    temp.setPrdImage("https://wxtest.guosen.com.cn/gsoss/8f2cf01233994c41bd51d72e38804984.png");
                } else if (temp.getPrdType() == 1 || temp.getPrdType() == 2) {
                    // 模版C
                    temp.setPrdImage("https://wxtest.guosen.com.cn/gsoss/db58ae436af74bfcaa502d6f3f825815.png");
                }
            }
            result.add(temp);
        }
        return result;
    }

    private String income(String s) {
        if (StrUtil.isEmpty(s)) {
            return "--";
        }
        try {
            String replace = s.replace("%", "");
            DecimalFormat decimalFormat = new DecimalFormat("#0.00");
            BigDecimal bigDecimal = new BigDecimal(replace);
            String format = decimalFormat.format(bigDecimal);
            return format + "%";
        } catch (Exception e) {
            log.info("转换错误:{}", e);
        }
        return "--";
    }

    @Override
    public boolean saveRoomGoods(GuoXinPrdInfoDTO dto) {
        if (dto.getList().size() > 20) {
            throw new BusinessException(60000, "房间最多关联20个产品", "");
        }
        RoomsEntity roomsEntity = roomMapper.selectById(dto.getIlId());
        if (roomsEntity == null) {
            log.info("保存房间商品：{}", dto);
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }
        if (roomsEntity.getStatus() == 1) {
            throw new BusinessException(60000, "房间直播中不允许添加", "");
        }
        LambdaQueryWrapper<RoomGoodsEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(RoomGoodsEntity::getIlId, roomsEntity.getIlId());
        roomGoodsMapper.delete(queryWrapper);
        for (GuoPrdInfoDTO infoDTO : dto.getList()) {
            RoomGoodsEntity roomGoodsEntity = new RoomGoodsEntity();
            BeanUtils.copyProperties(infoDTO, roomGoodsEntity);
            roomGoodsEntity.setPrdUseCase(infoDTO.getPrdUseCase());
            roomGoodsEntity.setId(null);
            roomGoodsEntity.setIlId(dto.getIlId());
            roomGoodsMapper.insert(roomGoodsEntity);
        }
        if (roomsEntity.getLiveRormal() == 1) {
            if (!Objects.equals(roomsEntity.getAuditStatus(), RoomAuditStatusEnum.SUBMIT_FOR_APPROVAL.getAuditStatus())) {
                roomsEntity.setAuditStatus(RoomAuditStatusEnum.SUBMIT_FOR_APPROVAL.getAuditStatus());
                roomMapper.updateById(roomsEntity);
            }
        }
        deleteRoomInfoToCache(roomsEntity);
        return true;
    }
    private void deleteRoomInfoToCache(RoomsEntity info) {
        // 设置两个缓存，一个是roonId,一个是ilId。在房间数据更新的时候删除掉缓存。
        String roomId = info.getRoomId();
        Integer ilId = info.getIlId();
        redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + roomId);
        redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + ilId);
        redisTemplate.delete(RedisKey.ROOM_ANCHOR_LIST_CACHE + ilId);
    }
    @Override
    public boolean delRoomGoods(GuoPrdInfoDTO dto) {
        if (dto.getId() == null) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }
        RoomGoodsEntity roomGoodsEntity = roomGoodsMapper.selectById(dto.getId());
        if (roomGoodsEntity == null) {
            throw new BusinessException(BizErrorCode.EMPTY_DATA);
        }
        RoomsEntity roomsEntity = roomMapper.selectById(roomGoodsEntity.getIlId());
        if (roomsEntity == null) {
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }
        if (roomsEntity.getStatus() == 1) {
            throw new BusinessException(60000, "房间直播中不允许删除", "");
        }
        roomGoodsEntity.setId(dto.getId());
        roomGoodsEntity.setIsDeleted(1);
        roomGoodsMapper.updateById(roomGoodsEntity);

        if (roomsEntity.getLiveRormal() == 1) {
            if (!Objects.equals(roomsEntity.getAuditStatus(), RoomAuditStatusEnum.SUBMIT_FOR_APPROVAL.getAuditStatus())) {
                roomsEntity.setAuditStatus(RoomAuditStatusEnum.SUBMIT_FOR_APPROVAL.getAuditStatus());
                roomMapper.updateById(roomsEntity);
            }
        }

        return true;
    }

    @Override
    public PageVO<GoodsStatisVO> getGoodsStatis(Integer ilId, int pageNum, int pageSize) {
        PageVO<GoodsStatisVO> pageVO = new PageVO<>();
        Page<RoomGoodsEntity> page = new Page<>(pageNum, pageSize);
        List<GoodsStatisVO> list = new ArrayList<>();
        LambdaQueryWrapper<RoomGoodsEntity> roomGoodsEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
        roomGoodsEntityLambdaQueryWrapper.eq(RoomGoodsEntity::getIlId, ilId);
        roomGoodsEntityLambdaQueryWrapper.eq(RoomGoodsEntity::getIsDeleted, 0);
        page = roomGoodsMapper.selectPage(page, roomGoodsEntityLambdaQueryWrapper);
        if (CollUtil.isEmpty(page.getRecords())) {
            return pageVO;
        }
        for (RoomGoodsEntity goodsEntity : page.getRecords()) {
            GoodsStatisVO goodsStatisVO = new GoodsStatisVO();
            goodsStatisVO.setPrdCode(goodsEntity.getPrdCode());
            goodsStatisVO.setPrdName(goodsEntity.getPrdName());

            LambdaQueryWrapper<LiveGoodsStatsEntity> liveGoodsStatsEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
            liveGoodsStatsEntityLambdaQueryWrapper.eq(LiveGoodsStatsEntity::getIlId, goodsEntity.getIlId());
            liveGoodsStatsEntityLambdaQueryWrapper.eq(LiveGoodsStatsEntity::getBgId, goodsEntity.getId());
            liveGoodsStatsEntityLambdaQueryWrapper.last(" limit 1");
            LiveGoodsStatsEntity statsEntity = liveGoodsStatsMapper.selectOne(liveGoodsStatsEntityLambdaQueryWrapper);
            if (statsEntity != null) {
                goodsStatisVO.setPushScreenCount(statsEntity.getPushScreenNum());
                goodsStatisVO.setPushScreenDuration(statsEntity.getDuration());
            }

            QueryWrapper<LiveGoodsStatsDetailEntity> queryWrapper = Wrappers.query();
            queryWrapper.select("user_id");
            queryWrapper.eq("il_id", goodsEntity.getIlId());
            queryWrapper.eq("bg_id", goodsEntity.getId());
            List<LiveGoodsStatsDetailEntity> liveGoodsStatsDetailEntities = liveGoodsStatsDetailMapper.selectList(queryWrapper);
            if (CollUtil.isEmpty(liveGoodsStatsDetailEntities)) {
                goodsStatisVO.setClickUserCount(0);
                goodsStatisVO.setClickCount(0);
            } else {
                goodsStatisVO.setClickCount(liveGoodsStatsDetailEntities.size());
                Set<Integer> collect = liveGoodsStatsDetailEntities.stream().map(LiveGoodsStatsDetailEntity::getUserId).collect(Collectors.toSet());
                goodsStatisVO.setClickUserCount(collect.size());
            }
            list.add(goodsStatisVO);
        }
        pageVO.setData(list);
        pageVO.setTotal((int) page.getTotal());
        pageVO.setCurrentPage(pageNum);
        return pageVO;
    }

}
